From 450e81d80056530edd6cfabbdd9e923137680c67 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 29 May 2015 13:35:29 -0700 Subject: [PATCH] Don't recurse so often in the dependency graph Prior to this commit the entire dependency tree would be traversed many, many times as the short circuits weren't applying fast enough. This commit modifies the recursion to only happen if the target in question was actually compiled. This commit saw a noop build time for Servo drop from 4.5s to 2.5s. --- src/cargo/ops/cargo_rustc/custom_build.rs | 4 +++- src/cargo/ops/cargo_rustc/mod.rs | 18 ++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index 1f7d427cb..8518f728f 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -7,7 +7,7 @@ use std::sync::Mutex; use core::{Package, Target, PackageId, PackageSet}; use util::{CargoResult, human, Human}; -use util::{internal, ChainError}; +use util::{internal, ChainError, profile}; use super::job::Work; use super::{fingerprint, process, Kind, Context, Platform}; @@ -41,6 +41,8 @@ pub struct BuildState { /// only run once (not twice). pub fn prepare(pkg: &Package, target: &Target, req: Platform, cx: &mut Context) -> CargoResult<(Work, Work, Freshness)> { + let _p = profile::start(format!("build script prepare: {}/{}", + pkg, target.name())); let kind = match req { Platform::Plugin => Kind::Host, _ => Kind::Target, }; let (script_output, build_output) = { (cx.layout(pkg, Kind::Host).build(pkg), diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index d10ab0efc..579e5a998 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -187,7 +187,6 @@ fn compile<'a, 'cfg>(targets: &[(&'a Target, &'a Profile)], cx: &mut Context<'a, 'cfg>, jobs: &mut JobQueue<'a>) -> CargoResult<()> { debug!("compile_pkg; pkg={}", pkg); - let profiling_marker = profile::start(format!("preparing: {}", pkg)); // For each target/profile run the compiler or rustdoc accordingly. After // having done so we enqueue the job in the right portion of the dependency @@ -200,6 +199,8 @@ fn compile<'a, 'cfg>(targets: &[(&'a Target, &'a Profile)], continue } + let profiling_marker = profile::start(format!("preparing: {}/{}", + pkg, target.name())); let work = if profile.doc { let rustdoc = try!(rustdoc(pkg, target, profile, cx)); vec![(rustdoc, Kind::Target)] @@ -232,6 +233,12 @@ fn compile<'a, 'cfg>(targets: &[(&'a Target, &'a Profile)], }; dst.push((Job::new(dirty, fresh), freshness)); } + drop(profiling_marker); + + // Be sure to compile all dependencies of this target as well. + for &(pkg, target, p) in cx.dep_targets(pkg, target, profile).iter() { + try!(compile(&[(target, p)], pkg, cx, jobs)); + } // If this is a custom build command, we need to not only build the // script but we also need to run it. Note that this is a little nuanced @@ -280,15 +287,6 @@ fn compile<'a, 'cfg>(targets: &[(&'a Target, &'a Profile)], jobs.queue(pkg, Stage::BuildCustomBuild).pop(); } } - drop(profiling_marker); - - // Be sure to compile all dependencies of this target as well. Don't recurse - // if we've already recursed, however. - for &(target, profile) in targets { - for &(pkg, target, p) in cx.dep_targets(pkg, target, profile).iter() { - try!(compile(&[(target, p)], pkg, cx, jobs)); - } - } Ok(()) } -- 2.30.2